#!/usr/bin/env python
#coding:utf-8
#copy from:http://lists.pyside.org/pipermail/pyside/2011-September/002907.html

import sys
from PySide.QtGui import *
from PySide.QtCore import *


class FourDimensionalTabWidget(QWidget):
     '''
     As a normal QTabWidget, but it's possible to show tabs on multiple
sides.
     '''

     def __init__(self, parent = None):
         '''
         Initialization.
         Set some default values.
         '''
         super(FourDimensionalTabWidget, self).__init__(parent)
         self.tabNorth = QTabBar(self)
         self.tabEast = QTabBar(self)
         self.tabSouth = QTabBar(self)
         self.tabWest = QTabBar(self)
         self.setRoundShape()
         self.connectTabs()

         self.content = QStackedWidget(self)
         self.content.addWidget(QWidget())
         self.content.setContentsMargins(6, 6, 7, 7)

         self.indexes = {}


     def setRoundShape(self):
         '''
         Show the tabs with round shape (default)
         '''
         self.tabNorth.setShape(QTabBar.RoundedNorth)
         self.tabEast.setShape(QTabBar.RoundedEast)
         self.tabSouth.setShape(QTabBar.RoundedSouth)
         self.tabWest.setShape(QTabBar.RoundedWest)

     def setTriangularShape(self):
         '''
         Show the tabs with triangular shape
         '''
         self.tabNorth.setShape(QTabBar.TriangularNorth)
         self.tabEast.setShape(QTabBar.TriangularEast)
         self.tabSouth.setShape(QTabBar.TriangularSouth)
         self.tabWest.setShape(QTabBar.TriangularWest)


     def paintEvent(self, event):
         '''
         Reimplemented to show the tabbars with the correct geometry.
         '''
         centerWidth = self.sizeHintCenter().width()
         centerHeight = self.sizeHintCenter().height()
         left = self.tabWest.sizeHint().width()
         top = self.tabNorth.sizeHint().height()
         right = left + centerWidth
         bottom = top + centerHeight

         self.tabNorth.setGeometry(left, 0, centerWidth, top)
         self.tabEast.setGeometry(right - 1, top - 1,self.tabEast.sizeHint().width(), centerHeight)
         self.tabSouth.setGeometry(left -1, bottom - 2, centerWidth,self.tabSouth.sizeHint().height())
         self.tabWest.setGeometry(0, top, left, centerHeight)
         self.content.setGeometry(left, top, centerWidth, centerHeight)

         super(FourDimensionalTabWidget, self).paintEvent(event)

     def sizeHint(self):
         '''
         Return sizeHint of content + 2 tabbars
         '''
         width = self.tabWest.sizeHint().width() +self.sizeHintCenter().width() + self.tabEast.sizeHint().width()
         height = self.tabNorth.sizeHint().height() +self.sizeHintCenter().height() + self.tabSouth.sizeHint().height()
         return QSize(width, height)

     def sizeHintCenter(self):
         '''
         Return sizeHint of the Content or if a tab needs more place in
this direction,
         return the tabs size.
         '''
         width = max([self.tabNorth.sizeHint().width(),self.tabSouth.sizeHint().width(), self.content.sizeHint().width()])
         height = max([self.tabWest.sizeHint().height(),self.tabEast.sizeHint().height(), self.content.sizeHint().height()])
         return QSize(width, height)

     def currentChanged(self):
         '''
         This slot is called when ever a tab changes.
         '''
         self.setCurrentIndex(self.tabNorth.currentIndex(),self.tabEast.currentIndex(), self.tabSouth.currentIndex(),self.tabWest.currentIndex())

     def setCurrentIndex(self, north, east, south, west):
         '''
         Show the content for the specified index. If one of the
orientations is not used,
         this value has to be '-1'.
         Example: tabWidget.setCurrentIndex(0, -1, -1, -1) if only the
north tabbar is used.
         '''
         index = (north, east, south, west)
         if index in self.indexes:
             self.content.setCurrentIndex(self.indexes[index])
         else:
             self.content.setCurrentIndex(0)

     def addContent(self, widget, north, east, south, west):
         '''
         Set the content for the specified index. If one of the
orientations is not used,
         this value has to be '-1'.
         Example: tabWidget.addContent(0, -1, -1, -1) if only the north
tabbar is used.
         '''
         self.indexes[(north, east, south, west)] =self.content.addWidget(widget)

     def addTabNorth(self, title):
         '''
         Add one tab to the tabNorth.
         '''
         self.tabNorth.addTab(title)

     def addTabEast(self, title):
         '''
         Add one tab to the tabEast.
         '''
         self.tabEast.addTab(title)

     def addTabSouth(self, title):
         '''
         Add one tab to the tabSouth.
         '''
         self.tabSouth.addTab(title)

     def addTabWest(self, title):
         '''
         Add one tab to the tabWest.
         '''
         self.tabWest.addTab(title)

     def connectTabs(self):
         '''
         Connect the 'currentChanged' signal of each tabbar with
currentChanged of this class.
         This shows the corresponding content for this tabs.
         '''
         self.tabNorth.currentChanged.connect(self.currentChanged)
         self.tabEast.currentChanged.connect(self.currentChanged)
         self.tabSouth.currentChanged.connect(self.currentChanged)
         self.tabWest.currentChanged.connect(self.currentChanged)

def setupFourDimensional(tabWidget):
     '''
     For test purpose only... Shows a four dimensional example.
     '''
     tabWidget.addTabEast('0. Tab')
     tabWidget.addTabEast('1. Tab')
     tabWidget.addTabEast('2. Tab')
     tabWidget.addTabWest('0. Tab')
     tabWidget.addTabWest('1. Tab')
     tabWidget.addTabSouth('0. Tab')
     tabWidget.addTabSouth('1. Tab')
     tabWidget.addTabNorth('0. Tab')
     tabWidget.addTabNorth('1. Tab')

     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 0, 0, 0)), 0, 0, 0, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 0, 0, 1)), 0, 0, 0, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 0, 1, 0)), 0, 0, 1, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 0, 1, 1)), 0, 0, 1, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 1, 0, 0)), 0, 1, 0, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 1, 0, 1)), 0, 1, 0, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 1, 1, 0)), 0, 1, 1, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (0, 1, 1, 1)), 0, 1, 1, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 0, 0, 0)), 1, 0, 0, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 0, 0, 1)), 1, 0, 0, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 0, 1, 0)), 1, 0, 1, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 0, 1, 1)), 1, 0, 1, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 1, 0, 0)), 1, 1, 0, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 1, 0, 1)), 1, 1, 0, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 1, 1, 0)), 1, 1, 1, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d,south: %d, west: %d' % (1, 1, 1, 1)), 1, 1, 1, 1)

     tabWidget.setCurrentIndex(0, 0, 0, 0)


def setupTwoDimensional(tabWidget):
     '''
     For test purpose only... Shows a two dimensional example.
     '''
     tabWidget.addTabWest('0. Tab')
     tabWidget.addTabWest('1. Tab')
     tabWidget.addTabNorth('0. Tab')
     tabWidget.addTabNorth('1. Tab')

     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d, south: %d, west: %d' % (0, -1, -1, 0)), 0, -1, -1, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d, south: %d, west: %d' % (0, -1, -1, 1)), 0, -1, -1, 1)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d, south: %d, west: %d' % (1, -1, -1, 0)), 1, -1, -1, 0)
     tabWidget.addContent(QLabel('Example Content:\nnorth: %d, east: %d, south: %d, west: %d' % (1, -1, -1, 1)), 1, -1, -1, 1)

     tabWidget.setCurrentIndex(0, -1, -1, 0)


if __name__ == '__main__':
     app = QApplication(sys.argv)
     tabWidget = FourDimensionalTabWidget()
     #setupFourDimensional(tabWidget)                # test 4 dim example, comment out to test 2 dim example
     setupTwoDimensional(tabWidget)                # uncomment to test 2dim example
     tabWidget.show()
     app.exec_()
